"""
6.2 文件的读写
本小节主要学习在操作系统中对文件的操作，包括文件的打开与关闭、文件的读写、文
件的追加、各种格式文件的解析等等。
6.2.1 文件打开与关闭
通过文件对象可以实现程序对文件的各种操作，因此在程序操作之前需要先生成文件对
象，这个过程就称为打开文件。文件对象在创建之后会占用一定的内存，同时会使得被打开
文件处于锁定状态，为了释放内存和文件锁，当文件使用结束后，需要对当前文件对象进行
释放，这个过程就称为关闭文件。
1. 文件打开
文件对象变量 = open(文件名, 打开模式)
open()函数用于打开文件，其中，第一个参数为待打开文件的文件名及路径，第二个参
数为打开模式，常用的打开方式包括'r'（只读）、'w'（写）、'a'（追加），其默认值为'r'。open()
函数打开文件后，会返回一个用于操作文件的文件对象，这个文件对象包含了对文件的各种
操作方法，在不同的打开模式下其对应的操作也各不相同，以下列出了 open()函数中不同打
开模式所对应的功能。
"""
"""
2. with…open…as 文件打开
由于文件读写时有可能产生输入输出错误 IOError，一旦出错，后面的 f.close()就不会被
调用。因此，为保证无论文件操作是否出错都能正确地关闭文件对象，Python 引入了 with 语
句以达到在异常状态下自动调用 close()方法的功能，其具体语法如下：
with open(文件名, 打开模式') as 文件对象变量:
执行语句（缩进代码块）
with 语法后接 open()函数，open()函数用于打开文件，并把文件对象返回。为了给文件
对象绑定一个变量名，在 open()函数后的 as 关键字跟随一个变量名，该变量名与 open()函数
返回的文件对象绑定在一起。文件操作执行语句需要在 with 语句的缩进的基础上再缩进 4
个空格，表示该语句块是在 with 控制的范围内。当该语句块执行过程中出现异常时，with 语
句可以保证文件对象 close()方法的执行。
"""
"""
练习:使用 with…open…as 方式打开一个名为 demo.txt 的文件，然后再关闭该文件。
"""
with open('demo.txt', 'w') as wf:
    print('ING')
print('over')
print("*" * 100)

"""
练习：使用with...open...as，在demo.txt文件中写入内容
"""
with open('demo.txt', 'w') as wf:
    wf.write(f'{"*" *10}Hello World!This is my <first> file!{"*" *10}')
print('Write Over')
print("*" * 100)

"""
练习：在文件中写入内容，并实现换行
"""
with open('demo2.txt', 'w') as wf2:
    wf2.write('Hello\nWorld\nPython')
print("Demo2 write over")

"""
2. writelines 方法
文件对象变量.writelines([字符串])
在获得写文件对象的情况下，使用 writelines()方法可以将 [字符串] 列表写入到文件中，
[字符串]为列表，该列表中每个元素必须为字符串类型，writelines()方法将列表中每个字符
串元素按顺序写入到文件中，如果需要每个字符串独占一行，则需要在每个字符串对象末尾
处包含换行转义符'\n'。
"""
"""
练习：使用writelines的方式实现文件的写入
"""
print("*" * 100)
print("开始使用writelines写入文件")
with open('demo3.txt', 'w') as wf3:
    wf3.writelines(['学号:123\n','姓名:张三\n','身高:180\n','体重:80\n'])
print("*" * 100)
"""
6.2.3 读文件
读取文件内容时，需要首先使用读模式’r’打开文件并获得文件对象变量 f，然后使用该文
件对象变量 f 调用文件对象中读文件的方法，包括 read()、readline()、readlines()等方法完成文件
内容读取。
1. read 方法
文件对象变量.read([读取长度])
在获得读文件对象的情况下，使用 read()方法可以将文件中的内容一次全部读取出来，作为
返回值赋给变量，如果需要指定读取长度，则可以在 read()方法中填写参数指定读取长度，从文
件中读取不超过读取长度的字符串。
"""
with open('demo.txt','r') as f:
    # 如果用这种方式读取大文件的话（GB、TB），读取文件时会占用大量的内存资源
    # 这种方式只适用于读取小文件
    buffer = f.read()
print(buffer)

"""
2. readline 方法
文件对象变量.readline([读取长度])
readline()与 read()方法不同，readline()一次读取一行文本，文本以回车换行为分隔符。如果
方法中含有读取长度参数，则 readline 读取的内容不超过读取长度所设定的范围。
"""
"""
练习：使用readline读取文件
"""
print("*" * 100)
print("开始使用readline来读取文件")
with open('demo_extend.txt', 'r') as f:
    #使用readline，就可以实现对大型数据的分割读取（每次读取一行）
    print(f.readline())
    print(f.readline())
    print(f.readline())
    print(f.readline())
    print(f.readline())

print("*" * 100)
print('这里使用for...in...的方式读取文件内容')
with open('demo_extend.txt', 'r') as f:
    for line in f:
        print(line, end='')

"""
3. readlines 方法
文件对象变量.readlines([读取长度])
184
readlines()方法用于读取文件中所有行(直到文件末尾结束符 EOF)并返回列表，该列表
包含了文件的所有内容，根据换行符分割成多个元素，每一行作为一个元素存储在 readlines()
返回的列表中。对此列表可使用 for... in ... 语法进行后续处理。readlines()中如果给定参数读
取长度，则实际文件读取内容不超过该参数设定的长度，如果碰到结束符 EOF 则返回空字
符串。
"""
"""
练习:使用readlines读取文件
"""
print("*" * 100)
print("开始使用readlines读取文件")
with open('demo_extend.txt','r') as f:
    lines = f.readlines()
print(f'获取的lines的类型为: {type(lines)}')
for line in lines:
    print(line, end='')

"""
6.2.4 追加文件
追加文件，首先使用追加模式'a'打开文件并获得文件对象变量 wf，然后使用文件对象变
量 wf，调用文件对象中写文件的方法，包括 write()、writelines()等。在追加模式下，所写入
的内容将追加在文件现有内容的尾部，不会覆盖原有内容。文件内容追加结束后同样需要对
文件对象进行关闭。
"""
"""
练习：使用'a'的读写模式，实现文件的追加
"""
print("*" * 100)
print("开始实现文件的追加(write)")
with open('demo.txt', 'a') as wf:
    wf.write('\nHello World!this is an append code!\n')
print("文件追加实现结束")
print("*" * 100)
print("开始实现文件的追加(writelines)")
with open('demo.txt', 'a') as wf:
    l = []
    for i in range(0,10):
        l.append(f'\nHello World!this is an append code!{i}\n')
    wf.writelines(l)
print("文件追加实现结束")


